package com.boss.core.util;

import com.boss.core.BossConstants;
import com.boss.core.BossGlobal;
import com.boss.core.manage.*;
import com.boss.core.user.BossUserProfile;
import hudson.model.Hudson;
import hudson.model.User;

import java.util.ArrayList;
import java.util.List;

/**
 * Global Utility class for BOSS
 * @author Momin Noor Khan
 */
public class BossGlobalUtil {

    //Global Properties DescriptorImpl
    public static BossGlobal.DescriptorImpl bossGlobalDescriptorImpl;

    public static BossConfiguration bossConfig;

    /**
     * Gets the Descriptor of Global BOSS properties
     *
     * @return
     */
    public static BossGlobal.DescriptorImpl getBossGlobalDescriptor() {
        try {
            bossGlobalDescriptorImpl = BossGlobal.DescriptorImpl.class.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return bossGlobalDescriptorImpl;
    }

    public static BossConfiguration getBossConfiguration() {
        try {
            bossConfig = BossConfiguration.class.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return bossConfig;
    }

    public static BossUserProfile.BossUserProperty getBossUserProperty(String userName) {
        User user = Hudson.getInstance().getUser(userName);
        BossUserProfile.BossUserProperty userProperty = null;
        if (user != null) {
            userProperty = user.getProperty(BossUserProfile.BossUserProperty.class);
        }
        return userProperty;
    }

    /**
     * Gets the general properties from the configuration specific to boss
     *
     * @return
     */
    public static List<BossProperty> getBossProperties() {
        return getBossConfiguration().getProperties();
    }

    public static String getPropertyValue(String key) {
        List<BossProperty> bProps = getBossProperties();
        for (BossProperty bp : bProps) {
            if (bp instanceof BossStringProperty) {
                if (bp.getName().equalsIgnoreCase(key)) {
                    return bp.getValue().toString();
                }
            }
        }
        return null;
    }

    /**
     * Gets the property sections from the configuration specific to boss
     *
     * @return
     */
    public static List<PropertySection> getPropertySections() {
        return getBossConfiguration().getPropertySections();
    }

    /**
     * Gets the specified property section from the configuration specific to Boss
     */
    public static PropertySection getPropertySection(String propertySectionName) {
        return getBossConfiguration().getPropertySection(propertySectionName);
    }

    public static List<BossEnvironment> getEnvironments() {
        return getBossConfiguration().getEnvironments();
    }

    public static List<BossEnvironment> getDisabledEnvironments() {
        return getBossConfiguration().getEnvironments(true);
    }

    public static List<BossEnvironment> getEnabledEnvironments() {
        return getBossConfiguration().getEnvironments(false);
    }

    public static List<BossServer> getServers(String environmentName) {
        return getBossConfiguration().getServers(environmentName);
    }

    public static List<BossServer> getDisabledServers(String environmentName) {
        return getBossConfiguration().getServers(environmentName, true);
    }

    public static List<BossServer> getEnabledServers(String environmentName) {
        return getBossConfiguration().getServers(environmentName, false);
    }

    public static List<BossPort> getPorts(String environmentName, String serverName) {
        return getBossConfiguration().getPorts(environmentName, serverName);
    }

    public static List<BossPort> getEnabledPorts(String environmentName, String serverName) {
        return getBossConfiguration().getPorts(environmentName, serverName, true);
    }

    public static List<BossPort> getDisabledPorts(String environmentName, String serverName) {
        return getBossConfiguration().getPorts(environmentName, serverName, false);
    }

    public static List<BossEnvironment> getEnvironments4User(String userName) {
        return getBossUserProperty(userName).getUserEnvironments();
    }

    public static List<BossEnvironment> getEnabledEnvironments4User(String userName) {
        return getBossUserProperty(userName).getUserEnvironments(false);
    }

    public static List<BossServer> getServers4User(String userName, String environmentName) {
        return getBossUserProperty(userName).getUserServers(environmentName);
    }

    public static List<BossServer> getEnabledServers4User(String userName, String environmentName) {
        return getBossUserProperty(userName).getUserServers(environmentName, false);
    }

    public static List<BossPort> getPorts4User(String userName, String environmentName, String serverName) {
        return getBossUserProperty(userName).getUserPorts(environmentName, serverName);
    }

    public static List<BossPort> getEnabledPorts4User(String userName, String environmentName,
                                                      String serverName) {
        return getBossUserProperty(userName).getUserPorts(environmentName, serverName, true);
    }

    public static List<String> getAvailableEnvironmentNames() {
        List<String> resultList = new ArrayList<String>();
        List<BossEnvironment> enabledEnvironments = getEnabledEnvironments();
        for(BossEnvironment e : enabledEnvironments){
            resultList.add(e.getEnvironmentName());
        }
        return resultList;
    }

    public static List<String> getAvailableServerNames(String environmentName){
        List<String> resultList = new ArrayList<String>();
        List<BossServer> enabledServers = getEnabledServers(environmentName);
        for(BossServer server : enabledServers){
            resultList.add(server.getServerName());
        }
        return resultList;
    }

    public static List<String> getAvailablePortNames(String environmentName, String serverName){
        List<String> resultList = new ArrayList<String>();
        List<BossPort> enabledPorts = getEnabledPorts(environmentName, serverName);
        for(BossPort port : enabledPorts){
            resultList.add(port.getPortName());
        }
        return resultList;
    }

    public static List<String> getAvailableEnvironmentNames4User(String userName){
        List<String> resultList = new ArrayList<String>();
        List<BossEnvironment> enabledEnvironments = getEnabledEnvironments();
        List<BossEnvironment> enabledEnvironments4User = getEnabledEnvironments4User(userName);
        for(BossEnvironment environment : enabledEnvironments4User){
            if(enabledEnvironments.contains(environment)){
                resultList.add(environment.getEnvironmentName());
            }
        }
        return resultList;
    }

    public static List<String> getAvailableServerNames4User(String userName, String environmentName){
        List<String> resultList = new ArrayList<String>();
        List<BossServer> enabledServers = getEnabledServers(environmentName);
        List<BossServer> enabledServers4User = getEnabledServers4User(userName, environmentName);
        for(BossServer server : enabledServers4User){
            if(enabledServers.contains(server)){
                resultList.add(server.getServerName());
            }
        }
        return resultList;
    }

    public static List<String> getAvailablePortNames4User(String userName, String environmentName, String serverName){
        List<String> resultList = new ArrayList<String>();
        List<BossPort> enabledPorts = getEnabledPorts(environmentName, serverName);
        List<BossPort> enabledPorts4User = getEnabledPorts4User(userName, environmentName, serverName);
        for(BossPort port : enabledPorts4User){
            if(enabledPorts.contains(port)){
                resultList.add(port.getPortName());
            }
        }
        return resultList;
    }

    /**
     * Gets the value of the specified property from the given property section
     *
     * @param propertySectionName
     * @param propertyKey
     * @return
     */
    public static String getPropertyValue(String propertySectionName, String propertyKey) {
        return getBossConfiguration().getPropertyValue(propertySectionName, propertyKey);
    }

    public static String getStagingDir(String project){
        return getPropertyValue(project, BossConstants.STAGING_DIR);
    }

    public static String getSvnStagingUrl(String project){
        return getPropertyValue(project, BossConstants.SVN_STAGING_URL);
    }

    public static String getSvnStagingPath(String project){
        return getPropertyValue(project, BossConstants.SVN_STAGING_PATH);
    }

    /**
     * Gets the default job delay for BOSS jobs from the global configuration settings done in Hudson.
     *
     * @return
     */
    public static String getJobDelay() {
        return getBossGlobalDescriptor().getJobDelay() + "sec";
        //return getPropertyValue("JOB_DELAY");
    }

    /**
     * Gets the path of the OC4JProfiles where the properties file for each target container is stored
     */
    public static String getOc4jProfilesPath() {
        return getBossGlobalDescriptor().getOc4jProfilesPath();
    }

    /**
     * Gets the path of the GISProfiles where the properties file for each target gis server is stored
     */
    public static String getGisProfilesPath() {
        return getBossGlobalDescriptor().getGisProfilesPath();
    }

    /**
     * Get the SVN username to be used for populating existing build drop-down (in PAM views)
     * @return
     */
    public static String getSvnUserName() {
        return getBossGlobalDescriptor().getSvnUserName();
    }

    /**
     * Get the SVN password for the configured SVN username
     * @return
     */
    public static String getSvnPassword() {
        return getBossGlobalDescriptor().getSvnPassword();
    }
}
